/*
 * @Author: Wangtao
 * @Date: 2022-07-26 14:26:31
 * @LastEditors: Wangtao
 * @LastEditTime: 2022-08-23 17:27:40
 */
import { camelize, CSSProperties, Directive, reactive } from 'vue'
import { BaseValue, itemPreCls, ItemProps, Props } from './interface'
import resizeobserver from './resizeobserver'
import { skeletonList } from './skeleton'

const SkeletonItem: Directive<any, BaseValue> = {
  mounted (el, binding) {
    const props: any = (skeletonList as any).findLast((e: any) => e.el.contains(el))
    if (!props) return
    const child = createItem(props, el, binding)
    props.targets.push(child)
  },
  beforeUnmount (el) {
    const props: any = (skeletonList as any).findLast((e: any) => e.el.contains(el))
    if (!props) return
    const i = props.targets.findIndex((e: any) => e.el === el)
    if (i < 0) return
    const child = props.targets[i]
    props.targets.splice(i, 1)
    resizeobserver.dispose(props.el, child.resizeCb)
  }
}

export default SkeletonItem

const createItem = (props: Props, el: ItemProps['el'], binding: ItemProps['binding']) => {
  el.classList.add(`${itemPreCls}-ref`)

  const { el: parentEl } = props

  const child: any = {
    el,
    binding,
    state: reactive({}),
    resizeCb: () => {
      const parentRect: any = parentEl.getBoundingClientRect(), parentStyle = getComputedStyle(parentEl)
      const style: any = getComputedStyle(el)
      const rect: any = el.getBoundingClientRect()
      const _style: any = { position: 'absolute' }
        // 对其位置
        ;['top', 'left'].forEach((e: any) => {
          const borderWidth: any = parseInt(parentStyle[(camelize(`border-${e}-width`) as any)])
          _style[e] = Math.abs(rect[e] - parentRect[e]) - borderWidth + 'px'
        })
        ;['width', 'height'].forEach(e => _style[e] = Math.ceil(rect[e]) + 'px')
      _style.borderRadius = style.borderRadius
      _style.zIndex = +style.zIndex + 1
      child.state.style = _style
    }
  }

  child.resizeCb()

  resizeobserver.observer(parentEl, child.resizeCb)

  return child
}